package com.mlnx.ecg.ui.panels;

import com.mlnx.ecg.ui.config.ECGConfig;
import com.mlnx.ecg.ui.config.ECGDeviceConstant;
import com.mlnx.ecg.ui.databuffer.HistoryEcgDatabuffer;
import com.mlnx.ecg.ui.databuffer.TimeEcgData;
import com.mlnx.ecg.ui.model.Channel;
import com.mlnx.ecg.ui.model.WavePos;
import com.mlnx.ecg.ui.style.WaveStyle;
import com.mlnx.ecg.ui.view.TimeWaveView;
import com.mlnx.ecg.ui.view.WaveView;

import javax.swing.*;
import javax.swing.border.EmptyBorder;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import java.awt.*;
import java.awt.event.ComponentEvent;
import java.awt.event.ComponentListener;
import java.awt.event.MouseWheelEvent;
import java.awt.event.MouseWheelListener;
import java.util.ArrayList;
import java.util.List;

public class SpecifiedEcgPanel extends JPanel {

    private List<WaveView> waveViews = new ArrayList<>();

    private boolean showGridding = true;

    private EcgShowType ecgShowType;

    private List<List<Object>> bufferList;

    private HistoryEcgDatabuffer historyEcgDatabuffer;

    private int start = 0;

    private Channel channel;

    public SpecifiedEcgPanel(Integer secondBuffer, List<TimeEcgData> timeEcgData,
                             EcgShowType ecgShowType) {
        super();
        historyEcgDatabuffer = new HistoryEcgDatabuffer(secondBuffer, timeEcgData);
        this.bufferList = historyEcgDatabuffer.getBufferList();
        this.ecgShowType = ecgShowType;

        setLayout(null);

        addListeners();
    }

    private void addListeners() {
        addComponentListener(new EcgComponentListener());

        addMouseWheelListener(new MouseWheelListener() {

            @Override
            public void mouseWheelMoved(MouseWheelEvent e) {
                Integer rotation = e.getWheelRotation();
                start += 200 * rotation;
                move();
            }
        });
    }

    public void clearChosenArea() {
        for (WaveView waveView : waveViews) {

            TimeWaveView timeWaveView = (TimeWaveView) waveView;

            timeWaveView.clearChoseTimePoints();
        }
    }

    // 波形前滚或者后滚
    public void move() {
        if (bufferList == null || bufferList.size() <= 0)
            return;

        if (start < 0)
            start = 0;

        if (start > bufferList.get(0).size()
                - waveViews.get(0).getMaxNumOfPoints())
            start = bufferList.get(0).size()
                    - waveViews.get(0).getMaxNumOfPoints();


        clearChosenArea();

        loadData(start);
        refreshUI();
    }

    private synchronized void initWaveView() {

        if (getHeight() == 0 || getWidth() == 0)
            return;

        setEcgShowType(ecgShowType);

        loadData(start);
        refreshUI();
    }

    public void refreshUI() {
        repaint();
        updateUI();
    }

    public synchronized void setShowGridding(boolean showGridding) {
        this.showGridding = showGridding;

        if (waveViews != null && waveViews.size() > 0) {
            for (WaveView waveView : waveViews) {
                waveView.setShowGridding(showGridding);
            }
        }
    }

    public synchronized void setEcgShowType(EcgShowType ecgShowType) {
        this.ecgShowType = ecgShowType;

        waveViews.clear();

        if (ecgShowType.equals(EcgShowType._1x1)) {
            ecgShowType = EcgShowType._1x12;
        }

        for (int i = 0; i < 12; ++i) {
            WaveView waveView = new TimeWaveView(EcgShowType.getWavePos(
                    ecgShowType, i, getWidth(), getHeight()), i,
                    ECGConfig.ECGLEADNAMES.get(i), ECGConfig.SAMPLING, ECGDeviceConstant.DEFAULT_SCALE, ECGDeviceConstant.DEFAULT_SPEED);
            waveView.setShowGridding(showGridding);

            waveViews.add(waveView);

        }

        if (ecgShowType.equals(EcgShowType._4x3)) {
            WaveView waveView = new TimeWaveView(EcgShowType.getWavePos(
                    this.ecgShowType, -1, getWidth(), getHeight()), 0,
                    ECGConfig.ECGLEADNAMES.get(0), ECGConfig.SAMPLING, ECGDeviceConstant.DEFAULT_SCALE, ECGDeviceConstant.DEFAULT_SPEED);

            waveView.setShowGridding(showGridding);
            waveViews.add(waveView);
        }

        if (this.ecgShowType.equals(EcgShowType._1x1)) {
            Channel channel = new Channel();
            channel.setChannelFlag(new boolean[]{true, false, false, false,
                    false, false, false, false, false, false, false, false});
            setChannel(channel);
        }

        if (ecgShowType.equals(EcgShowType._1x7)) {
            Channel channel = new Channel();
            channel.setChannelFlag(new boolean[]{true, true, true, true,
                    true, true, true, false, false, false, false, false});
            setChannel(channel);
        }
    }

    public synchronized void setChannel(Channel channel) {

        this.channel = channel;

        waveViews.clear();

        List<WavePos> wavePoss = EcgShowType.getWavePos(channel, getWidth(),
                getHeight());
        List<Integer> list = channel.getSelectChannelFlag();
        for (int i = 0; i < list.size(); i++) {
            String ecgLeadName = ECGConfig.ECGLEADNAMES.get(list.get(i));
            if (channel.isvLeadAsV5() && ecgShowType.equals(EcgShowType._1x7)
                    && i == 6) {
                ecgLeadName = "V5";
            }

            WaveView waveView = new TimeWaveView(wavePoss.get(i), list.get(i),
                    ecgLeadName, ECGConfig.SAMPLING, ECGDeviceConstant.DEFAULT_SCALE, ECGDeviceConstant.DEFAULT_SPEED);
            waveView.setShowGridding(showGridding);
            waveViews.add(waveView);
        }
    }

    public void loadData(int start) {
        if (bufferList == null || bufferList.size() <= 0)
            return;

        synchronized (SpecifiedEcgPanel.this) {

            if (waveViews != null && waveViews.size() > 0) {

                for (WaveView waveView : waveViews) {
                    waveView.earsePoints();
                }

                for (int i = start, j = 0; j < waveViews.get(0)
                        .getMaxNumOfPoints(); i++, j++) {

                    for (WaveView waveView : waveViews) {

                        if (bufferList.get(waveView.getFlag()).size() > i) {

                            try {
                                HistoryECGData data = (HistoryECGData) bufferList
                                        .get(waveView.getFlag()).get(i);

                                if (data == null) {
                                    break;
                                }

                                ((TimeWaveView) waveView).updatePoint(
                                        data.getValue(), data.getPacketTime(),
                                        data.getNumber() + "");
                            } catch (ArrayIndexOutOfBoundsException e) {
                                break;
                            }
                        }

                    }
                }
            }
        }

        repaint();
    }

    @Override
    public synchronized void paint(Graphics g) {
        super.paint(g);

        if (waveViews != null && waveViews.size() > 0) {
            for (WaveView waveView : waveViews) {
                waveView.doDraw((Graphics2D) g, false, WaveStyle.BG_COLOR,
                        WaveStyle.FRAME_COLOR, WaveStyle.TEXT_COLOR,
                        WaveStyle.ECG_COLOR);
            }
        }
    }

    class EcgComponentListener implements ComponentListener {

        @Override
        public void componentResized(ComponentEvent e) {
            initWaveView();
        }

        @Override
        public void componentMoved(ComponentEvent e) {
            // TODO Auto-generated method stub

        }

        @Override
        public void componentShown(ComponentEvent e) {
            // TODO Auto-generated method stub

        }

        @Override
        public void componentHidden(ComponentEvent e) {
            // TODO Auto-generated method stub

        }

    }

}
